package com.sneakxy.mybatis.commons.dialect;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.session.Configuration;
import org.springframework.data.domain.Pageable;

public class OracleDialect extends Dialect {

	public static final String DIALECT_NAME = "ORACLE";
	
	public static final String REGEX_KEY = "REGEXP_LIKE";
	
	/**
	 * @param configuration
	 */
	public OracleDialect(Configuration configuration) {
		super(configuration);
	}

	@Override
	protected ProcessHandler onProcess(String sql, Map<String, Object> parameterValues, Pageable page) {
		final StringBuilder _sql = new StringBuilder();
		long offset = page.getOffset();
		List<ParameterMapping> _params = new ArrayList<ParameterMapping>();
		boolean hasOffset = offset > 0;
		_params.add(new ParameterMapping.Builder(this.getConfiguration(), "offsetEnd", Long.class).build());
		if (hasOffset) {
			_params.add(new ParameterMapping.Builder(this.getConfiguration(), "offset", Long.class).build());
			_sql.append("select * from (");
		}
		_sql.append("select row_page_.*, rownum rownum_ from (");
		_sql.append(sql);
		_sql.append(") row_page_ where rownum <= ?");
		if (hasOffset) {
			_sql.append(") where rownum_ > ?");
		}
		return new ProcessHandler(_sql.toString(), _params);
	}

	@Override
	protected boolean isProcessed(String sql, Map<String, Object> parameterValues, Pageable page) {
		return StringUtils.contains(sql, "row_page_");
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybatis.commons.dialect.Dialect#setProcessedParameters(java.util.Map, org.springframework.data.domain.Pageable)
	 */
	@Override
	protected void setParameterValues(Map<String, Object> parameterValues, Pageable page) {
		parameterValues.put("offset", page.getOffset());
		parameterValues.put("offsetEnd", page.getOffset() + page.getPageSize());
	}

	@Override
	public String buildRegexSql(String column, String value) {
		return StringUtils.join(REGEX_KEY, "(", column, ", ", value, ")");
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybatis.commons.dialect.Dialect#needSequenceIdColumnSql()
	 */
	@Override
	public boolean needSequenceIdColumnSql() {
		return true;
	}

	@Override
	protected String formatSimpleColumnName(String columnName) {
		return StringUtils.join("\"", StringUtils.upperCase(columnName), "\"");
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybatis.commons.dialect.Dialect#getSequenceIdColumnValue(java.lang.String)
	 */
	@Override
	public String getSequenceIdColumnValue(String generator) {
		return new StringBuilder().append(generator).append(".NEXTVAL").toString();
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybatis.commons.dialect.Dialect#getSequenceIdSql(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public String getSequenceIdSql(String generator, String idColumn) {
		return new StringBuilder()
				.append("SELECT ")
				.append(generator)
				.append(".CURRVAL FROM DUAL").toString();
	}

	/* (non-Javadoc)
	 * @see com.sneakxy.mybatis.commons.dialect.Dialect#upperFunction(java.lang.String)
	 */
	@Override
	public String upperFunction(String column) {
		return new StringBuilder().append("NLS_UPPER(").append(column).append(")").toString();
	}

}
